iT邦幫忙

0

day 11 「讀取使用者輸入」,用 Scanner 讀取 host 和 port

  • 分享至 

  • xImage
  •  

Scanner 是 Java 內建的輸入工具,用來讀取使用者輸入。

String host = readHost(scanner);
int[] range = readPortRange(scanner);
從已建立的 Scanner scanner 呼叫你之前寫好的兩個輸入處理函式,回傳 host 字串 和 回傳一個 int 陣列 [startPort, endPort]。接著你通常會把它們傳給掃描函式去開始掃描。
package day1;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

public class Day11Demo {
public static void main(String[] args) {
try (Scanner scanner = new Scanner(System.in)) {
String host =readHost(scanner);
int[] range = readPortRange(scanner);

        System.out.println("\n===== 設定完成 =====");
        System.out.println("Host: " + host);

        try{ InetAddress resolved = InetAddress.getByName(host);
            System.out.println("Resolved IP: " + resolved.getHostAddress());
        }catch (UnknownHostException e) {
            System.out.println("無法解析 host: " + host);
        }System.out.println("Port 範圍: " + range[0] + " ~ " + range[1]);

        startScan(host, range[0], range[1]);
    }
}
private static String readHost(Scanner scanner) {
    while (true) {
        System.out.println("請輸入host:" );
        String host = scanner.nextLine().trim();
        if (!host.isEmpty()) return host;
        System.out.println("Host 不能為空,請重新輸入。");
    }
}

private static int[] readPortRange(Scanner scanner) {
    while (true) {
        System.out.println("請輸入 Port 或範圍 (例如 80 或 20-1024):");
        String line = scanner.nextLine().trim();
        try {
            return parsePortRange(line);
        }catch (IllegalArgumentException ex) {
            System.out.println("輸入錯誤:"+ex.getMessage());

        }
    }
}

private static int[] parsePortRange(String input){
    if (input.isEmpty())throw new IllegalArgumentException("不能為空");
    if (!input.contains("-")){
        int p =parsePortNumber(input);
        return new int[]{p,p};
    }
    String[] parts=input.split("-",2);
    int start=parsePortNumber(parts[0].trim());
    int end=parsePortNumber(parts[1].trim());
    if (start > end) throw new IllegalArgumentException("起始 port 不能大於結束 port。");
    return new int[] { start, end };
}

private static int parsePortNumber(String s){
    try{
        int p = Integer.parseInt(s);
        if(p<1 || p>65535) throw new IllegalArgumentException("Port 必須在 1-65535。");
        return p;
    }catch (NumberFormatException e) {
        throw new IllegalArgumentException("Port 必須為整數。");
    }
}
private static void startScan(String host, int startPort, int endPort) {
System.out.println("\n開始掃描...");
for (int port = startPort; port <= endPort; port++) {
    try (Socket socket = new Socket()) {
        socket.connect(new java.net.InetSocketAddress(host, port), 1000);
        System.out.printf("Port %d -> OPEN%n", port);
    } catch (IOException e) {
        System.out.printf("Port %d -> CLOSED/TIMEOUT%n", port);
      }
  }
System.out.println("掃描結束。");

}

}
1.private static String readHost(Scanner scanner)
用途:讀使用者輸入的 host(例如 localhost ),保證不會是空字串。
2. private static int[] readPortRange(Scanner scanner)
用途:讀使用者輸入的 port 或 port 範圍(例如 80 或 20-1024),保證格式正確且範圍合法。
3. private static int[] parsePortRange(String input)
用途:把使用者輸入的字串解析成 [startPort, endPort] 陣列。
簡單理解:把 "80" → [80, 80],把 "20-1024" → [20, 1024],並檢查數字合法性。
4. private static int parsePortNumber(String s)
用途:把字串轉成整數 port,並檢查是否在 1~65535 範圍內。
5. private static void startScan(String host, int startPort, int endPort)
用途:用 Socket 逐個掃描指定範圍內的 port,並印出 OPEN 或 CLOSED/TIMEOUT。
簡單理解:真正開始掃描 port,把結果印出來。

今天這段程式碼用箭頭圖解釋:

使用者啟動程式


讀取 Host (readHost)

├─> 如果空字串 → 提示重新輸入 → 回到讀取 Host


讀取 Port 範圍 (readPortRange)

├─> 如果格式錯誤或超出範圍 → 提示重新輸入 → 回到讀取 Port


解析 Host 名稱 (InetAddress.getByName)

├─> 成功 → 印出 Resolved IP

└─> 失敗 → 印出「無法解析 host」 → 可以結束程式或重新輸入


開始掃描 Port (startScan)

├─> 迴圈從 startPort 到 endPort
│ │
│ ▼
│ 嘗試連線 Socket
│ │
│ ├─> 成功 → 印出 Port X -> OPEN
│ │
│ └─> 失敗/超時 → 印出 Port X -> CLOSED/TIMEOUT


掃描結束 → 印出「掃描結束。」


程式結束

過程中遇到的問題:
不懂InetAddress.getByName(host) 做了什麼?
它會嘗試把使用者輸入的 host 名稱 轉換成 IP 位址
例如: "localhost" → "127.0.0.1"
"google.com" → "142.250.190.78"(每次可能不同)

今天學到了用 Scanner 讓輸入者輸入 host,接下來輸入port範圍,程式也會看有沒有錯誤,也用了迴圈,直到輸入成功為止,然後查詢host的IP位址。
最後開始掃描輸入者輸入port的範圍,每個port都會掃描是否開啟(CLOSED/TIMEOUT)。也有用到昨天學習的Socket, 用 try-with-resources 每次連線掃描後自動關閉。


圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言